Import Heightmap for nameshing with 3dsmax
Import Heightmap for Nameshing with 3dsmax By Mschoeldgen LEVEL: 'Advanced '''Tools: ' 3ds Max 9, BF2 plugin for 3ds Max 9 (This is the last version that has plugins for 3ds Max), notepad or another text editor This is an expansion to the original plugin 3ds max 9 tools for importing the heightmap of the map. This comes in very handy for adjusting navmeshes to the exact terrain as we all know that maps with smooth valleys and hills are often victims of the 'over-optimizing' in navmesh.exe, in which vehicles are abandoned in valleys and bots stand around there, or even game crashes. You'll need 3DSMax and the appropriate BF2 toolset for your version of the program. A text editor is needed to modify the scripts. The scripts are located in '''<3DSMax>/scripts/bf2 Ok, first open the 'BF2_UI.mcr' file with a texteditor and add the following lines (between two other menu entries) : macroScript BF2Import_Heightmap buttontext:"BF2 Import Heightmap" category:"Game Tools BF2" toolTip:"BF2 Import Heightmap" ( bf2ImportScaledHeightmap() ) I put those lines between BF2GameTools_LMs and BF2GameTools_Batch when using the PoE2 toolset in Max9. Scroll further down in that file and add the line in the middle: append ItemsTemp (menuMan.createActionItem "BF2GameTools_LMs" "Game Tools BF2") append ItemsTemp (menuMan.createActionItem "BF2Import_Heightmap" "Game Tools BF2") append ItemsTemp (menuMan.createActionItem "BF2GameTools_Batch" "Game Tools BF2") Save the file and close it. Now we need to find the heightmap import function used for the lightmapping toolchain and clone it. Go to /scripts/bf2/levels/Heightmap_Import.ms and open it with your texteditor. Add the following code at the end. ( Rexman has left in a 'TEST' section at the end of the file , insert the code before that section ) : ---------------------------------------------------------- -- Creates the scaled terrain mesh with same scale as navmeshes -- heightmap is flipped added by mschoeldgen aug 2008 fn BF2generatescaledHM worldSize:4096 values:#(1,2,3,4,5,6,7,8,9) = ( undo off ( local res = sqrt values.count local evenRes = res - 1 local t = mesh width:evenRes length:evenRes lengthSegs:evenRes widthSegs:evenRes format " res: %\n" res -- set vertex positions local tmpYOffset for y = 0 to evenRes do ( tmpYOffset = y * res + 1 for x=0 to evenRes do ( setVert t (tmpYOffset + x) [ x, y, values[ tmpYOffset + x ] ] ) ) ) return t ) --------------------------------------------------------------------------------------------- fn BF2_ImportscaledHeightmapRaw fname tScale:1,1,1 s:1.0 = ( format "HeightmapFile: %\n" fname local f = fopen fname "rb" if f undefined then ( format "ERROR! Could not open file: %\n" fname return false ) fseek f 0 #seek_end local theFileSize = ftell f format " FileSize: %\n" theFileSize fseek f 0 #seek_set local hmRes = (sqrt (theFileSize / 2)) as integer format " Heightmap res: %\n" hmRes local hmVals = #() for y=1 to hmRes do ( for x=1 to hmRes do ( append hmVals (readShort f #unsigned) ) ) fclose f local t = BF2generatescaledHM worldsize:(hmRes * s) values:hmVals if isValidNode t then ( t.scale = tScale * s ) return t ) fn bf2ImportScaledHeightmap fname:undefined s:1.0= ( if fname undefined then ( fname = getOpenFileName types:"HeightData.con(*.con)|HeightData.con|All(*.*)|*.*|" ) if fname undefined then return false local heightData = bf2parseConData_HeightData fname local tScale = heightData2 local tRawFile = heightData3 if tScale undefined then ( format "ERROR! heightmap has no scale value!\n" return false ) if tRawFile undefined then ( format "ERROR! heightmap has no .raw filename!\n" return false ) local findPos = findString fname "\\levels\\" if findPos undefined then ( format "Error Could not find Levels in path!\n" return false ) local gamePath = substring fname 1 findPos format "tScale.y: %\n" tScale.y tScale = [ tScale.x, tScale.z , tScale2 ] local t = BF2_ImportscaledHeightmapRaw (gamePath + tRawFile) tScale:tScale s:s addModifier t (uvwmap()) t = convertToMesh t t.wirecolor = brown -- bf2 has the origin at the bottom center of the terrain t.pos.x = -0.5 * t.max.x t.pos.y = -0.5 * t.max.y -- but the pivot is in the center t.pivot = 0,0,0 bf2AddMirrorMod t t.Mirror.mirror_axis = 1 t.Mirror.mirror_center.position = 0,0,0 t.Mirror.mirror_center.position.x = 0 t.Mirror.mirror_center.position.y = 0 t.Mirror.mirror_center.position.z = 0 return t ) You'll probably note that most of these functiosn are nearly identical to the existing functions but with a different scale ( 1 instead of 10 ) and that the function adds a mirror modifier to the imported heightmap. This comes in handy later on. * Save the file and quit the text editor. After Max has been started you'll notice a new entry in the Battlefield 2 menu : 'BF2 Import Heightmap' Now to import the navmesh you're currently working on: navmesh_example1 * Go to the new menu entry and select it. * Browse to the heightdata.con of your level and open it. Heightmaps are mostly large objects so from that point on your Max will probably be a bit slower. Unfortunately, there's a bug in Maxscript which ignores setting the center of the mirror modifier, so we need to do that manually once the heightmap is imported. * Select it (it's called 'Object01') and select the 'Mirror Center' property of its mirror modifier ( Step 1 in the image below ) . * Select Max' 'Move' tool and find the three coordinates for the mirror center on the bottom status line . * It currently says something like X = -1024.0 Y=-1024 Z=0 if you imported a 1024 scale 2 map. heightmap_navmesh1 * Enter a 0 ( zero, that is ) into the X and the Y coordinate and the heightmap is exactly where you want it. * As the final step collapse the Mirror modifier on the heightmap mesh heightmap_navmesh2 Now edit your navmesh as usual. For best results: * ·vehicle navmeshes should be set between 0 and 1 meter above the ground * ·infantry navmeshes should follow the terrain as close as possible. * ·tesselating a polygon (set the 'explode' value to 0 before tesselating ) enables you to add detail in critical spots.